import * as vscode from 'vscode';
import * as path from 'path';
import { BundleService } from '../service/bundleService';
import { Bundle } from './bundleProvider';
import configurationInstance from '../service/configurationService';

class Project extends vscode.TreeItem {
    constructor(
        public readonly projectId: number,
        public readonly label: string,
        public readonly collapsibleState: vscode.TreeItemCollapsibleState
    ) {
        super(label, collapsibleState);
        this.projectId = projectId;
        this.tooltip = `${this.label}`;
    }

    iconPath = {
        light: path.join(__filename, '..', '..', 'resources', 'cloud.svg'),
        dark: path.join(__filename, '..', '..', 'resources', 'cloud.svg')
    };
}

export default class ProjectProvider implements vscode.TreeDataProvider<Project>{
    private bundleService;

    private _onDidChangeTreeData: vscode.EventEmitter<Project | undefined | null | void> = new vscode.EventEmitter<Project | undefined | null | void>();
    readonly onDidChangeTreeData: vscode.Event<Project | undefined | null | void> = this._onDidChangeTreeData.event;

    private projects: Project[] = [];

    private mode = 'view';

    constructor(context: vscode.ExtensionContext, mode: 'view' | 'watch' = 'view' ) {
        this.bundleService = new BundleService();

        this.mode = mode;

        if (mode === 'view') {
            this.init();
        } else {
            this.loadWatches();
        }

        configurationInstance.on('reload', () => {
            if (mode === 'view') {
                this.projects = [];
                this.refresh();
                this.init();
            } else {
                this.loadWatches();
                this.refresh();
            }
        });
    }

    async init() {
        const success = await this.bundleService.login();
        if (success) {
            const res = await this.bundleService.fetchProjects();
            const projects = res.data.data;

            this.projects = projects.map((item: any) => {
                return new Project(item.id, item.name, vscode.TreeItemCollapsibleState.None);
            });

            //refresh
            this.refresh();
        }
    }

    async loadWatches() {
        const success = await this.bundleService.login();
        if (success) {
            const res = await this.bundleService.fetchProjects();
            const projects = res.data.data || [];
            const projectItems: Project[] = projects.map((item: any) => {
                return new Project(item.id, item.name, vscode.TreeItemCollapsibleState.None);
            });

            const watchesProjects = configurationInstance.configuration.get('watches');
            for(const watch of watchesProjects as string[]) {
                const exist = projectItems.find((item) => item.label === watch);
                if(exist) {
                    this.watch(exist);
                }
            }
            this.refresh();
        }
    }

    refresh(): void {
        if (this.mode === 'view') {
            this._onDidChangeTreeData.fire();
        }


        if (this.mode === 'watch') {
            this._onDidChangeTreeData.fire();
        }
    }

    getTreeItem(element: Project): Project {
        return element;
    }

    getChildren(element?: Project): Thenable<Project[]> {
        if (!element) {
            return Promise.resolve(this.projects);
        } else {
            return new Promise(async resolve => {
                let res;

                try {
                    res = await this.bundleService.fetchBundles(element.projectId);
                } catch(err) {
                    resolve([]);
                }
               
                if(res) {
                    const bundles = res.data.data.map((item: any) => {
                        return new Bundle(item.id, item.name, item.path, vscode.TreeItemCollapsibleState.None);
                    });
                    resolve(bundles);
                } else {
                    resolve([]);
                }
            });
        }
    }

    watch(item: Project) {
        if (!this.exist(item)) {
            // const watches = configurationInstance.configuration.get('watches');
            // (watches as string[]).push(item.label);
            // configurationInstance.configuration.update('watches', watches);
            const bundleProject = {...item, collapsibleState: 1};
            this.projects.push(bundleProject);
            this.refresh();
        }
    }

    remove(item: Project) {
        if (this.exist(item)) {
            const index = this.projects.findIndex(project => project.projectId === item.projectId);
            this.projects.splice(index, 1);
            const configuration = this.projects.map(item => item.label);
            configurationInstance.configuration.update('watches', configuration);
            this.refresh();
        }
    }

    exist(item: Project) {
        return this.projects.findIndex(project => project.projectId === item.projectId) >= 0;
    }
}